package utils

import (
	"fmt"
	"log"
	"os"
	"path/filepath"
	"text/template"
	"time"

	"gorm.io/gorm"
)

// RequestEntityConfig 请求实体生成配置
type RequestEntityConfig struct {
	DB                *gorm.DB
	DatabaseName      string
	PackageName       string
	OutputPath        string
	Tables            []string      // 指定要生成的表，空表示所有表
	IgnoreFields      []string      // 忽略的字段名
	EmbedStructs      []EmbedStruct // 嵌入的结构体
	IgnoreStructsTags []string      // 传递给 generateTag 使用的字段
}

// RequestTemplateData 请求实体模板数据
type RequestTemplateData struct {
	PackageName       string
	TableName         string
	TableComment      string
	Columns           []ColumnInfo
	EmbedStructs      []EmbedStruct
	GenerateTime      string
	IgnoreStructsTags []string // 传递给 generateTag 使用的字段
}

// GenerateRequestEntities 生成请求实体类（合并到单个文件）
func GenerateRequestEntities(config RequestEntityConfig) error {
	tableList, err := getTables(config.DB, config.DatabaseName, config.Tables)
	if err != nil {
		return fmt.Errorf("获取表信息失败: %v", err)
	}

	// 确保输出目录存在
	if err := os.MkdirAll(config.OutputPath, 0755); err != nil {
		return fmt.Errorf("创建输出目录失败: %v", err)
	}

	for _, table := range tableList {
		columns, err := getColumns(config.DB, config.DatabaseName, table.TableName)
		if err != nil {
			return fmt.Errorf("获取表 %s 的列信息失败: %v", table.TableName, err)
		}

		// 过滤忽略的字段
		filteredColumns := filterIgnoredFields(columns, config.IgnoreFields)

		// 生成合并的请求实体文件
		if err := generateMergedRequestFile(config, table, filteredColumns); err != nil {
			return fmt.Errorf("生成表 %s 的请求实体文件失败: %v", table.TableName, err)
		}
	}

	return nil
}

// generateMergedRequestFile 生成合并的请求实体文件
func generateMergedRequestFile(config RequestEntityConfig, table TableInfo, columns []ColumnInfo) error {
	// 准备模板数据
	templateData := prepareMergedRequestTemplateData(config, table, columns)

	// 生成文件名
	fileName := fmt.Sprintf("%s_req.go", toSnakeCase(table.TableName))
	filePath := filepath.Join(config.OutputPath, fileName)

	// 确保目录存在
	if err := os.MkdirAll(config.OutputPath, 0755); err != nil {
		log.Printf("无法创建目录: %v\n", err)
		return err
	}

	// 创建文件
	file, err := os.Create(filePath)
	if err != nil {
		log.Printf("文件创建失败: %v\n", err)
		return err
	}
	defer file.Close()

	// 解析并执行模板
	tmpl := template.Must(template.New("mergedRequest").Funcs(template.FuncMap{
		"toCamelCase": toCamelCase,
		"goType":      goType,
		"generateTag": generateTag, // 使用统一的标签生成函数
	}).Parse(mergedRequestTemplate))

	// 执行模板渲染
	err = tmpl.Execute(file, templateData)
	if err != nil {
		log.Printf("模板渲染失败: %v\n", err)
		return err
	}

	// 输出生成成功的日志
	log.Printf("成功生成请求实体文件: %s\n", filePath)
	return nil
}

// prepareMergedRequestTemplateData 准备合并的请求实体模板数据
func prepareMergedRequestTemplateData(config RequestEntityConfig, table TableInfo, columns []ColumnInfo) RequestTemplateData {
	data := RequestTemplateData{
		PackageName:       config.PackageName,
		TableName:         table.TableName,
		TableComment:      table.TableComment,
		Columns:           columns,
		EmbedStructs:      config.EmbedStructs,
		GenerateTime:      time.Now().Format("2006-01-02 15:04:05"),
		IgnoreStructsTags: config.IgnoreStructsTags,
	}

	return data
}

// mergedRequestTemplate 合并的请求实体模板
const mergedRequestTemplate = `// Code generated by request-gen. DO NOT EDIT.
// Generated at: {{.GenerateTime}}
package {{.PackageName}}

// {{toCamelCase .TableName}}AddReq 新增{{.TableComment}}请求
type {{toCamelCase .TableName}}AddReq struct {
	{{range .EmbedStructs}}
	{{.Name}} {{.Type}}
	{{end}}
	{{range .Columns}}
	{{- if ne .ColumnKey "PRI"}} // {{.Comment}}
	{{- $goType := goType .DataType .ColumnType .IsNullable .MaxLength .ForceType .ColumnDefault}}  
	{{toCamelCase .Name}} {{$goType}} {{generateTag . $.IgnoreStructsTags}}  
	{{end}}
	{{end}}
}

// {{toCamelCase .TableName}}EditReq 修改{{.TableComment}}请求
type {{toCamelCase .TableName}}EditReq struct {
	{{range .EmbedStructs}}
	{{.Name}} {{.Type}}
	{{end}}
	{{range .Columns}}
	{{- if eq .ColumnKey "PRI"}} // {{.Comment}} (主键)
	{{- $goType := goType .DataType .ColumnType .IsNullable .MaxLength .ForceType .ColumnDefault}}  
	{{toCamelCase .Name}} {{$goType}} {{generateTag . $.IgnoreStructsTags}}  
	{{else}}
	{{- $goType := goType .DataType .ColumnType .IsNullable .MaxLength .ForceType .ColumnDefault}}  
	{{toCamelCase .Name}} {{$goType}} {{generateTag . $.IgnoreStructsTags}}  
	{{end}}
	{{end}}
}

// {{toCamelCase .TableName}}PageReq 分页查询{{.TableComment}}请求
type {{toCamelCase .TableName}}PageReq struct {
	// 当前页码
	Page int ` + "`" + `form:"page" json:"page" comment:"当前页码"` + "`" + `
	// 每页条数
	PageSize int ` + "`" + `form:"pageSize" json:"pageSize" comment:"每页条数"` + "`" + `
	// 排序字段（字段驼峰名称，如：createTime）
	SortField *string ` + "`" + `form:"sortField" json:"sortField" comment:"排序字段（字段驼峰名称，如：createTime）"` + "`" + `
	// 排序方式（升序=asc、降序=desc || 默认=asc）
	SortOrder *string ` + "`" + `form:"sortOrder" json:"sortOrder" comment:"排序方式（升序=asc、降序=desc）"` + "`" + `
	// 搜索关键词
	SearchKey *string ` + "`" + `form:"searchKey" json:"searchKey" comment:"搜索关键词"` + "`" + `

}
`

// 定义 not 函数，用于模板中的逻辑判断
func not(b bool) bool {
	return !b
}
